package org.convallaria.infrastruct.db.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;

/**
 * 自定义数据源配置属性
 * 
 * @author gjh
 * @since 2024-09-24
 */
@Data
@ConfigurationProperties(prefix = "convallaria.datasource")
public class CustomDataSourceProperties {

    /**
     * 慢SQL监控配置
     */
    @Valid
    @NestedConfigurationProperty
    private SlowSql slowSql = new SlowSql();

    /**
     * 连接池监控配置
     */
    @Valid
    @NestedConfigurationProperty
    private Monitor monitor = new Monitor();

    /**
     * 性能优化配置
     */
    @Valid
    @NestedConfigurationProperty
    private Performance performance = new Performance();

    /**
     * 慢SQL监控配置
     */
    @Data
    public static class SlowSql {
        
        /**
         * 是否启用慢SQL监控
         */
        @NotNull
        private Boolean enabled = true;

        /**
         * 慢查询阈值（毫秒）
         */
        @Min(value = 1, message = "慢查询阈值必须大于0")
        private Long threshold = 1000L;

        /**
         * 是否启用详细SQL日志
         */
        @NotNull
        private Boolean enableLog = true;

        /**
         * 是否打印慢查询警告
         */
        @NotNull
        private Boolean printWarning = true;

        /**
         * 是否记录SQL参数
         */
        @NotNull
        private Boolean logParameters = false;

        /**
         * 慢SQL日志级别 (DEBUG, INFO, WARN, ERROR)
         */
        @NotNull
        private String logLevel = "WARN";

        /**
         * 最大SQL长度限制（超过此长度将被截断）
         */
        @Min(value = 100, message = "SQL长度限制不能少于100字符")
        private Integer maxSqlLength = 1000;
    }

    /**
     * 连接池监控配置
     */
    @Data
    public static class Monitor {
        
        /**
         * 是否启用连接池监控
         */
        @NotNull
        private Boolean enabled = true;

        /**
         * 监控统计周期（秒）
         */
        @Min(value = 10, message = "监控周期不能少于10秒")
        private Integer period = 60;

        /**
         * 是否启用JMX监控
         */
        @NotNull
        private Boolean jmxEnabled = true;

        /**
         * 连接池警告阈值（百分比）
         */
        @Min(value = 50)
        private Integer warningThreshold = 80;
    }

    /**
     * 性能优化配置
     */
    @Data
    public static class Performance {
        
        /**
         * 是否启用查询缓存
         */
        @NotNull
        private Boolean cacheEnabled = false;

        /**
         * 最大缓存条目数
         */
        @Min(value = 10, message = "最大缓存条目数不能少于10")
        private Integer maxCacheSize = 1000;

        /**
         * 缓存过期时间（分钟）
         */
        @Min(value = 1, message = "缓存过期时间不能少于1分钟")
        private Integer cacheExpireMinutes = 30;

        /**
         * 缓存清理间隔（分钟）
         */
        @Min(value = 1, message = "缓存清理间隔不能少于1分钟")
        private Integer cacheCleanupInterval = 10;

        /**
         * 批量操作大小
         */
        @Min(value = 100)
        private Integer batchSize = 1000;

        /**
         * 是否启用懒加载
         */
        @NotNull
        private Boolean lazyLoadingEnabled = true;

        /**
         * 查询超时时间（秒）
         */
        @Min(value = 1)
        private Integer queryTimeout = 30;

        /**
         * 是否启用二级缓存
         */
        @NotNull
        private Boolean secondLevelCacheEnabled = false;

        /**
         * 缓存内存使用阈值（百分比）
         * 当内存使用超过此阈值时，会拒绝新的缓存请求
         */
        @Min(value = 50)
        @jakarta.validation.constraints.Max(value = 95)
        private Integer cacheMemoryThreshold = 80;
    }

    // ===== 便捷访问方法 =====

    /**
     * 获取慢SQL阈值
     */
    public Long getSlowSqlThreshold() {
        return slowSql.getThreshold();
    }

    /**
     * 是否启用慢SQL监控
     */
    public Boolean isSlowSqlEnabled() {
        return slowSql.getEnabled();
    }

    /**
     * 是否启用SQL日志
     */
    public Boolean isSqlLogEnabled() {
        return slowSql.getEnableLog();
    }

    /**
     * 获取批量操作大小
     */
    public Integer getBatchSize() {
        return performance.getBatchSize();
    }

    /**
     * 获取监控周期
     */
    public Integer getMonitorPeriod() {
        return monitor.getPeriod();
    }

    // ===== 验证方法 =====

    /**
     * 验证配置的有效性
     */
    public void validate() {
        if (slowSql.getThreshold() != null && slowSql.getThreshold() <= 0) {
            throw new IllegalArgumentException("慢查询阈值必须大于0");
        }
        
        if (monitor.getPeriod() != null && monitor.getPeriod() < 10) {
            throw new IllegalArgumentException("监控周期不能少于10秒");
        }
        
        if (performance.getBatchSize() != null && performance.getBatchSize() < 1) {
            throw new IllegalArgumentException("批量操作大小必须大于0");
        }
    }
}